<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
<script>

  const obj = {
    name: {
      msg: [2, 3, 4],
      age: {
        aa: 'a'
      }
    },
    aa: {
      name: '234'
    }
    // next: obj
  }

  obj.next = obj
  // // 为什么死循环
  // // 原有复杂数据类型重新拷贝一份(给他一个新的指针或者地址)，不能影响原有数据
  // // 如果说内部有了对象的循环引用了，我是不是只需要深拷贝其中任何一个，然后直接复用拷贝好的结果，不用每次重新递归
  //
  // // 如何缓存拷贝的结果
  // // 预期：每拷贝一次对象，都给他缓存起来，下次只要遇到这个对象，直接去缓存里面拿结果
  //
  // // 我的缓存变量的数据结构是什么样的？
  // // {
  // //   '源数据对象'
  // // :
  // //   '拷贝之后的结果1',
  // //     '源数据对象2'
  // //   '拷贝之后的结果2'
  // // }
  //
  // // console.log(deepCopy(obj))
  function deepCopy(data) {
    const map = new Map() // 键可以是一个对象
    function dp(data) {
      const existObj = map.get(data) // 看一下当前需要处理的数据是否已经被处理过(只要处理过了，都会通过map缓存起来)
      if (existObj) {
        //  已经被处理过了，第二次见到这个对象了(相同的引用的地址)
        //  只要返回上次处理之后的结果
        return existObj
      }
      let result = Array.isArray(data) ? [] : {};
      map.set(data, result)
      for (const key in data) {
        let item = data[key]
        if (typeof item === 'object') {
          result[key] = dp(item)
        } else {
          result[key] = item
        }
      }
      return result
    }

    return dp(data)
  }

  console.log(deepCopy(obj))

  function a() {
    console.log(1)
  }

  // const b = a.bind(null)
  // b()
  // console.log(a === b)
  // console.log(b)

  // const a = {}
  // const c = {}
  //
  // const b = {}
  // console.log(a.toString())
  // b[a] = 1;
  // b[c] = 2
  //
  // const fn = function () {
  //   console.log('234234')
  // }
  //
  // console.dir(fn.__proto__) // Function.prototype.toString
  //
  // // const a = {} // Object
  //
  // console.log(a.toString()) // 是不是顶层的toStrin
  // console.log(a.toString === Object.prototype.toString)
  //
  // a.toString()
  //
  // function getDataType(data) {
  //   const type = Object.prototype.toString.call(data)
  //   return type.substring(8, type.length - 1)
  // }
  //
  // console.log(getDataType({}))
  //
  // console.log(getDataType([]))
  // console.log(getDataType(true))
  // // 对象结构有一个缺点：key只能是字符串，不是一个字符串，默认回去调用数据的toString进行转化
  //
  // // map
  // // 可以使用对象作为key
  // const map = new Map()
  //
  // const tempObj = {name: '黑马'}
  // // console.log({name: '黑马'} === {name: '黑马'})
  // // map.set({name: '黑马'}, {name: '传智'})
  // // console.log(map.get({name: '黑马'}))
  // // console.log([] === []) // 打印什么？
  //
  // // console.log([] === [])
  // // console.log({} === {})
</script>
</body>
</html>
